#pragma once
#include "SocketAddress.h"
#include "io/InputStream.h"
#include "io/OutputStream.h"
#include <shared_mutex>

namespace yzrilyzr_net{
	EBCLASS(Socket){
	private:
	std::shared_mutex stateLock;
	bool closed=false;
	bool created=false;
	bool bound=false;
	bool connected=false;
	bool shutIn=false;
	bool shutOut=false;
	std::shared_ptr<yzrilyzr_io::InputStream> in=nullptr;
	std::shared_ptr<yzrilyzr_io::OutputStream> out=nullptr;
	public:
	void * implData;
	Socket();
	~Socket();
	void bind(std::shared_ptr<SocketAddress> addr);
	void connect(std::shared_ptr<SocketAddress> addr){
		connect(addr, 0);
	}
	void connect(std::shared_ptr<SocketAddress> addr, int32_t timeout);

	bool isClosed(){
		std::unique_lock<std::shared_mutex> lock(stateLock);
		return closed;
	}
	bool isBound(){
		std::unique_lock<std::shared_mutex> lock(stateLock);
		return bound;
	}
	bool isConnected(){
		std::unique_lock<std::shared_mutex> lock(stateLock);
		return connected;
	}
	bool isOutputShutdown(){
		std::unique_lock<std::shared_mutex> lock(stateLock);
		return shutOut;
	}
	bool isInputShutdown(){
		std::unique_lock<std::shared_mutex> lock(stateLock);
		return shutIn;
	}
	std::shared_ptr<yzrilyzr_io::InputStream> getInputStream();
	std::shared_ptr<yzrilyzr_io::OutputStream> getOutputStream();
	void close();
	void shutdownInput();
	void shutdownOutput();
	//set options
	void setSoTimeout(int32_t timeout);
	void setSoLinger(bool on, int32_t linger);
	void setKeepAlive(bool on);
	void setOOBInline(bool on);
	void setReuseAddress(bool on);
	void setTcpNoDelay(bool on);
	void setSendBufferSize(int32_t size);
	void setReceiveBufferSize(int32_t size);
	void setTrafficClass(int32_t tc);
	//get options
	int32_t getSoTimeout();
	int32_t getSoLinger();
	bool getKeepAlive();
	bool getOOBInline();
	bool getReuseAddress();
	bool getTcpNoDelay();
	int32_t getSendBufferSize();
	int32_t getReceiveBufferSize();
	int32_t getTrafficClass();
	};
}